home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
pascal
/
memmap.zip
/
FIG.5
< prev
next >
Wrap
Text File
|
1989-05-17
|
11KB
|
219 lines
MEMMAP.PAS 5/17/89 0:47
1 {$M 4000,0,0}
2 PROGRAM MemMap;
3
4 {MemMap shows a Memory Map of all programs and environment blocks.
5
6 Usage: MEMMAP to show all Memory Control Blocks (MCBs)
7 or
8 MEMMAP /V to show MCBs and all environment variables
9 (the /V option is ignored in DOS 2.X or lower)
10
11 (C) Copyright 1989, Earl F. Glynn, Overland Park, KS.
12 All Rights Reserved.
13
14 This program may be freely distributed for non-commercial use.
15
16 MemMap is based on PCMAP from PC Magazine, SHOWMEM from "The
17 Waite's Group MS-DOS Developer's Guide" (Second Edition), and
18 the DOS 4.0 MEM /DEBUG command.
19
20 Version 1.0 -- 27 February 1989.
21
22 Version 2.0 -- 17 May 1989.
23 Modifications were made to handle IBM's INDCIPL program (part of
24 the 3270 Workstation Program). Memory with it has a large number
25 of contiguous MCBs each pointing to a zero-length block. Termination
26 conditions were modified to avoid possible problems when an MCB
27 is not tagged "correctly".}
28
29
30 USES DOS; {DOSVersion,Intr,Registers}
31
32 CONST
33 EnvironmentBlock: STRING[12] = 'Environment ';
34 ProgramBlock : STRING[12] = 'Program ';
35
36 TYPE
37 MemoryControlBlock = {MCB -- only needed fields are shown}
38 RECORD
39 Blocktag : BYTE; {tag is M ($4D) except last is Z ($5A)}
40 BlockOwner : WORD; {if nonzero, process identifier, usually PID}
41 BlockSize : WORD; {size in 16-byte paragraphs (excludes MCB)}
42 misc : ARRAY[1..3] OF BYTE; {placeholder}
43 ProgramName: ARRAY[1..8] OF CHAR {only used by DOS 4.0; ASCIIZ}
44 END; {PID normally taken from PSP}
45 ProgramSegmentPrefix = {PSP -- only needed fields are shown}
46 RECORD { offset }
47 PSPtag : WORD; { $20CD or $27CD if PSP} { 00 $00 }
48 misc : ARRAY[1..21] OF WORD; { 02 $02 }
49 Environment: WORD { 44 $2C }
50 END;
51
52 VAR
53 DOSVerNum: BYTE; {major version number, e.g., 3 for 3.X}
54 LastSize : WORD; {used to detect multiple null MCBs}
55 MCB : ^MemoryControlBlock;
56 NullMCB : WORD; {counter of MCBs pointing to 0-length blocks}
57 r : Registers; {TYPE defined in DOS unit}
58 segment : WORD;
59 vflag : BOOLEAN; {Verify flag TRUE when /V specified}
60
61 FUNCTION W2X(w: WORD): STRING; {binary word to hex character string}
62 CONST HexDigit: ARRAY[0..15] OF CHAR = '0123456789ABCDEF';
63 BEGIN {similar to REXX standard D2X function}
64 W2X := HexDigit[Hi(w) SHR 4] + HexDigit[Hi(w) AND $0F] +
65 HexDigit[Lo(w) SHR 4] + HexDigit[Lo(w) AND $0F];
66 END {W2X}; {change in CONST above suggested by Neil J. Rubenking}
67
68 PROCEDURE ProcessMCB; {Each Memory Control Block}
69 VAR {is processed by this PROCEDURE.}
70 b : CHAR;
71 Blocktype: STRING[12];
72 bytes : LongInt;
73 EnvSize : WORD;
74 i : WORD;
75 last : CHAR;
76 MCBenv : ^MemoryControlBlock;
77 MCBowner : ^MemoryControlBlock;
78 psp : ^ProgramSegmentPrefix;
79 BEGIN
80 IF (MCB^.BlockTag <> $4D) AND (MCB^.BlockTag <> $5A) AND
81 (MCB^.BlockTag <> $00)
82 THEN BEGIN
83 IF NullMCB > 0
84 THEN WRITELN (NullMCB:6,' contiguous MCBs pointing to empty ',
85 'blocks not shown.');
86 WRITELN ('Unknown Memory Control Block Tag ''',MCB^.BlockTag,
87 '''.');
88 WRITELN ('MemMap scan terminated.');
89 HALT
90 END;
91 IF (MCB^.BlockSize = 0) AND (LastSize = 0)
92 THEN INC (NullMCB) {Count but don't output multiple null MCBs}
93 ELSE BEGIN
94 LastSize := MCB^.BlockSize;
95 IF NullMCB > 0
96 THEN BEGIN
97 WRITELN (NullMCB:6,' contiguous MCBs pointing to empty ',
98 'blocks not shown.');
99 NullMCB := 0
100 END
101 ELSE BEGIN
102 bytes := LongInt(MCB^.BlockSize) SHL 4; {size of MCB in bytes}
103 WRITE (W2X(segment):6,W2X(MCB^.BlockSize):8,'0',bytes:9,
104 W2X(MCB^.BlockOwner):8,' ');
105
106 IF MCB^.BlockOwner = 0
107 THEN WRITELN ('Free Space <unallocated>')
108 ELSE BEGIN
109 psp := Ptr(MCB^.BlockOwner,0); {possible PSP}
110 {Almost all programs have a tag of $20CD; DOS MODE is one
111 that uses $27CD in some versions.}
112 IF (psp^.PSPtag <> $20CD) AND (psp^.PSPtag <> $27CD)
113 THEN WRITELN ('System ', {not valid PSP}
114 '<DOS ',DosVerNum,'.',Hi(DOSVersion),' kernel>')
115 ELSE BEGIN {valid program segment prefix}
116 MCBenv := Ptr(psp^.Environment-1,0); {MCB of environment}
117 BlockType := 'Data '; {assume}
118 IF MCB^.Blockowner = (segment + 1)
119 THEN BlockType := ProgramBlock
120 ELSE
121 IF psp^.Environment = (segment + 1)
122 THEN BlockType := EnvironmentBlock;
123 WRITE (BlockType:12,' ');
124 IF MCB^.BlockOwner <> MCBenv^.BlockOwner
125 THEN
126 IF DOSVerNum <> 4
127 THEN WRITELN ('<unknown>') {different owner; unknown in 3.X}
128 ELSE BEGIN {in DOS 4.0 short name is in MCB}
129 MCBowner := Ptr(MCB^.Blockowner-1,0); {MCB of owner block}
130 i := 1;
131 WHILE (MCBowner^.ProgramName[i] <> #$00) AND (i < 9) DO BEGIN
132 WRITE (MCBowner^.ProgramName[i]);
133 INC (i)
134 END;
135 WRITELN
136 END
137 ELSE BEGIN {environment must have same owner as MCB}
138 IF DOSVerNum < 3
139 THEN WRITELN ('<unknown>') {DOS 1.X or 2.X}
140 ELSE BEGIN {DOS 3.X}
141 EnvSize := MCBenv^.BlockSize SHL 4; {multiply by 16}
142 i := 0;
143 b := CHAR( Mem[psp^.Environment:i] );
144 REPEAT
145 last := b; {skip through ASCIIZ environment variables}
146 INC (i);
147 b := CHAR( Mem[psp^.Environment:i] );
148 UNTIL (i > EnvSize) OR ( (b = #$00) AND (last = #$00));
149 INC (i); {end of environment block is $0000}
150 b := CHAR( Mem[psp^.Environment:i] );
151 IF (i >= EnvSize) OR (b <> #$01) {valid signature?}
152 THEN WRITE ('<shell>') {shell is probably COMMAND.COM}
153 ELSE BEGIN
154 INC (i,2); {skip process signature $0001}
155 b := CHAR( Mem[psp^.Environment:i] );
156 REPEAT
157 WRITE (b); {output process name byte-by-byte}
158 INC (i);
159 b := CHAR( Mem[psp^.Environment:i] )
160 UNTIL (i > EnvSize) OR (b = #$00);
161 END;
162 WRITE